#ifndef __HDMI_CEC_H__
#define __HDMI_CEC_H__

#include <linux/gpio.h>
#include <linux/interrupt.h>
#include "hdmi_core.h"
#include <linux/regulator/consumer.h>
#include <linux/err.h>

#define hdmi_cec_reg_offset 0x214
#define hdmi_cec_enable_reg_bit_offset 0x800
#define hdmi_cec_write_reg_bit_offset 0x200
#define hdmi_cec_read_reg_bit_offset 0x100

//polling message time unit : ns
#define HDMI_CEC_PRE_POLLING_MESSAGE_TIME 600000
#define HDMI_CEC_WAIT_BROADCAST_COMPLETE 30000000

//send frame time unit:ns
#define HDMI_CEC_PRE_SEND_MESSAGE_TIME 600000

#define HDMI_CEC_START_BIT_LOW_TIME 3700000
#define HDMI_CEC_START_BIT_HIGH_TIME 800000

#define HDMI_CEC_PULL_LOW_TIME 200000

#define HDMI_CEC_DATA_BIT_LOGICAL0_LOW_TIME 1500000
#define HDMI_CEC_DATA_BIT_LOGICAL1_LOW_TIME 600000
#define HDMI_CEC_DATA_BIT_WHOLE_TIME 2400000

#define HDMI_CEC_DATA_BIT_ACK_INVALID_TIME 400000
#define HDMI_CEC_DATA_BIT_ACK_SET_LOW_TIME 1400000

#define HDMI_CEC_CONTINUE_SEND_ANOTHER_MESSAGE 20000000

//receive frame time unit:ns
#define HDMI_CEC_JUDGE_START_BIT_TIME 1900000
#define HDMI_CEC_CONFIRM_START_BIT_TIME 2200000
#define HDMI_CEC_CONFIRM_LOGICAL_BIT_TIME 1000000

#define __Cinf(msg...)       {printk(KERN_WARNING "[CEC] ");printk(msg);}
#define __Cmsg(msg...)       {printk(KERN_WARNING "[CEC] file:%s,line:%d:    ",__FILE__,__LINE__);printk(msg);}
#define __Cwrn(msg...)       {printk(KERN_WARNING "[CEC WRN] file:%s,line:%d:    ",__FILE__,__LINE__); printk(KERN_WARNING msg);}
#define __Cerr(msg...)       {printk(KERN_WARNING "[CEC WRN] file:%s,line:%d:    ",__FILE__,__LINE__); printk(KERN_ERR msg);}

#define HDMI_CEC_OSD_NAME  "AW_A31S"

typedef enum {
    pre_polling_mes,
    start_polling_bit,
    polling_mes_set_info_bit,
    polling_mes_set_eom_bit,
    polling_mes_set_ack_bit,
    polling_mes_get_ack_bit,
    continue_polling_mes,
    complete_polling_mes,
}__hdmi_cec_polling_message_status;

typedef enum {
    pre_send_mes,
    start_bit,
    header_block_set_info_bit,
    header_block_set_eom_bit,
    header_block_set_ack_bit,
    header_block_get_ack_bit,
    opcode_block_set_info_bit,
    opcode_block_set_eom_bit,
    opcode_block_set_ack_bit,
    opcode_block_get_ack_bit,
    oprands_block_set_info_bit,
    oprands_block_set_eom_bit,
    oprands_block_set_ack_bit,
    oprands_block_get_ack_bit,
    wait_for_hdmi_connect,
    continue_send_mes,
}__hdmi_cec_send_frame_status;

typedef enum {
    judge_start_bit,
    confirm_start_bit,
    header_block_receive_info_bit,
    header_block_receive_eom_bit,
    header_block_ack_bit_pull_down,
    header_block_ack_bit_pull_up,
    data_block_receive_info_bit,
    data_block_receive_eom_bit,
    data_block_ack_bit_pull_down,
    data_block_ack_bit_pull_up,
}__hdmi_cec_receive_frame_status;

typedef enum {
    HDMI_CEC_LADDR_TV,
    HDMI_CEC_LADDR_RECORDER1,
    HDMI_CEC_LADDR_RECORDER2,
    HDMI_CEC_LADDR_TUNER1,
    HDMI_CEC_LADDR_PLAYER1,
    HDMI_CEC_LADDR_AUDIO,
    HDMI_CEC_LADDR_TUNER2,
    HDMI_CEC_LADDR_TUNER3,
    HDMI_CEC_LADDR_PLAYER2,
    HDMI_CEC_LADDR_RECORDER3,
    HDMI_CEC_LADDR_TUNER4,
    HDMI_CEC_LADDR_PLAYER3,
    HDMI_CEC_LADDR_RESERVED1,
    HDMI_CEC_LADDR_RESERVED2,
    HDMI_CEC_LADDR_SPECIFIC,
    HDMI_CEC_LADDR_BROADCAST,
}__hdmi_cec_logical_address;

typedef enum {
    HDMI_CEC_IMAGE_VIEW_ON                 = 0x04,
    HDMI_CEC_TEXT_VIEW_ON                  = 0x0d,
    HDMI_CEC_GIVE_DECK_STATUS              = 0x1a,
    HDMI_CEC_DECK_STATUS                   = 0x1b,
	HDMI_CEC_SET_MENU_LANGUAGE             = 0x32,
    HDMI_CEC_STANDBY                       = 0x36,
    HDMI_CEC_PLAY                          = 0x41,
    HDMI_CEC_DECK_CONTROL                  = 0x42,
    HDMI_CEC_SET_OSD_NAME                  = 0x47,
    HDMI_CEC_SENT_ROUTING_INFORMATION      = 0x81,
	HDMI_CEC_ACTIVE_SOURCE                 = 0x82,
    HDMI_CEC_REPORT_PHY_ADDR               = 0X84,
    HDMI_CEC_REQUEST_ACTIVE_SOURCE         = 0x85,
    HDMI_CEC_SENT_VERDOR_ID                = 0x87,
	HDMI_CEC_SENT_VERDOR_COMMAND           = 0x89,
    HDMI_CEC_MENU_STATE                    = 0x8e,
    HDMI_CEC_GIVE_POWER_STATUS             = 0x8f,
    HDMI_CEC_REPORT_POWER_STATUS           = 0x90,
	HDMI_CEC_GET_MENU_LANGUAGE             = 0x91,
    HDMI_CEC_INACTIVE_SOURCE               = 0x9d,
	HDMI_CEC_REPORT_CEC_VERSION            = 0x9e,
}__hdmi_cec_opcode;

typedef enum {
    HDMI_CEC_MSG_EOM_MORE,
    HDMI_CEC_MSG_EOM_END,
}__hdmi_cec_msg_eom;

typedef enum {
    HDMI_CEC_MSG_ACK_NORMAL,
    HDMI_CEC_MSG_ACK_BROADCAST,
}__hdmi_cec_msg_ack;

typedef enum {
    PIN_FAIL     	= -24,
	PIN_NUM_ERR   	= -25,
	GPIO_ERR       = -26,
}__hdmi_cec_err;

typedef struct {
	__bool hdmi_cec_used;
	__u32  hdmi_cec_pin;
	__u32  hdmi_cec_pin_num;
}__hdmi_cec_cfg;

typedef struct {
    __u32 header_block;
    __hdmi_cec_polling_message_status sta;
    __u32 status_flags;
    __u32 broadcast_flags;
    __u32 broadcast_complete_flags;
}__hdmi_cec_polling_message_data;

typedef struct {
    __hdmi_cec_send_frame_status sta;
    __hdmi_cec_logical_address indicate_logical_adr;
    __hdmi_cec_logical_address follower_logical_adr;
    __u32 header_block;
    __hdmi_cec_msg_eom eom;
    __hdmi_cec_msg_ack ack;
    __u32 flags;
    __u32 oprands_count;
    __u32 oprands_num;
    __u32 resend_flags;
    __u32 opcode_flags;
    __u32 current_buf_flags;
    __u32 add_buf_flags;
    __u32 status_flags;
}__hdmi_cec_send_frame_data;

typedef struct {
    u32 irq_request_handle;
    __hdmi_cec_receive_frame_status sta;
    __u32 header_block;
    __hdmi_cec_msg_eom eom;
    __hdmi_cec_msg_ack ack;
    __u32 flags;
    __u32 receive_frame;
    __u32 oprands_count;
    __u32 opcode_flags;
    __u32 add_buf_flags;
    __u32 current_buf_flags;
}__hdmi_cec_receive_frame_data;

typedef struct {
    __u32 oprands_num;
    __u32 opcode_flags;
    __u32 follower_adr;
    __u32 opcode;
    __u32 oprands[14];
}__hdmi_cec_send_message;

typedef struct {
    __u32 oprands_num;
    __u32 opcode;
    __u32 oprands[14];
}__hdmi_cec_receive_message;

struct msg_to_send {
    struct nlmsghdr *nlh;
	__hdmi_cec_receive_message sec;
};

__u32 hdmi_cec_get_pin(void);
__u32 hdmi_cec_get_pin_num(void);
__u32 hdmi_cec_set_gpio(__u32 pin,__u32 num);
void hdmi_cec_clear_polling_flags(void);
int __disp_set_cec_hdmi_ch(void);
void hdmi_cec_polling_message(void);
void hdmi_send_message(__hdmi_cec_send_message *mes);
void hdmi_cec_start_receive_frame(void);
u32 hdmi_cec_gpio_irq_hdl(void *para);
__u32 hdmi_cec_get_initiator_adr(void);
__u32 hdmi_cec_receive_message(__hdmi_cec_receive_message * receive);
int hdmi_cec_sent_sock_skb(__hdmi_cec_receive_message* rec);
void hdmi_cec_nl_input(struct sk_buff* skb);
int hdmi_cec_close_flag(void);
void hdmi_cec_init(void);
void hdmi_cec_exit(void);

#endif
